home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / paswiz14.zip / PASWIZ.DOC < prev    next >
Text File  |  1993-05-26  |  46KB  |  1,301 lines

  1.                   The Pascal Wizard's Library
  2.                   =-------------------------=
  3.                           Version 1.4
  4.  
  5.     PasWiz  Copyright (c) 1990-1993  Thomas G. Hanlin III
  6.  
  7.  
  8.  
  9. This is PasWiz, a library of assorted routines for use with
  10. Turbo Pascal, Quick Pascal, and compatible compilers. Full
  11. Pascal source code is now included with the shareware version.
  12. Assembly language sources are provided to registered owners. The
  13. PasWiz collection is copyrighted, but may be distributed as long
  14. as the following conditions are met:
  15.  
  16.    All PasWiz files must be distributed together as a unit in
  17.    unmodified form. No files may be left out or added.
  18.  
  19. YOU USE THIS LIBRARY AT YOUR OWN RISK. It has been tested by me
  20. on my own computer, but I will not assume any responsibility for
  21. any problems which PasWiz may cause you. If you run into a
  22. problem, please let me know about it, and I will do my best to
  23. verify and repair the error.
  24.  
  25. Shareware operates on a "try before you buy" basis. It is
  26. expected that if you find PasWiz useful, you will register your
  27. copy. You may not use PasWiz routines in programs intended for
  28. distribution unless you have registered. Registration entitles
  29. you to receive the latest version of PasWiz, complete with full
  30. source code. See the ORDER.FRM file for details.
  31.  
  32. So who's the Pascal Wizard? With PasWiz, you are! Read this tome
  33. well, for invoking these routines without proper preparation may
  34. bring unexpected results. Cape and hat (optional) not included.
  35.  
  36.                       Table of Contents                  page 2
  37.  
  38.  
  39.  
  40.  Overview and Legal Info .................................... 1
  41.  
  42.  BCD Math ................................................... 3
  43.  
  44.  Equipment Info ............................................. 7
  45.  
  46.  Expression Evaluator ...................................... 10
  47.  
  48.  Extensions to Pascal's Math ............................... 11
  49.  
  50.  Joystick Support .......................................... 13
  51.  
  52.  Keyboard Control .......................................... 14
  53.  
  54.  String Stuff .............................................. 18
  55.  
  56.  Music ..................................................... 22
  57.  
  58.  Mouse ..................................................... 23
  59.  
  60.                            BCD Math                      page 3
  61.  
  62.                            Unit: BCD
  63.  
  64.  
  65.  
  66. Some of you may not have heard of BCD math, or at least not have
  67. more than a passing acquaintance with the subject. BCD (short
  68. for Binary-Coded Decimal) is a way of encoding numbers. It
  69. differs from the normal method of handling numbers in several
  70. respects. On the down side, BCD math is much slower than normal
  71. math and the numbers take up more memory. However, the benefits
  72. may far outweigh these disadvantages, depending on your
  73. application: BCD math is absolutely precise within your desired
  74. specifications, and you can make a BCD number as large as you
  75. need. If your applications don't require great range or
  76. precision out of numbers, normal Pascal math is probably the
  77. best choice. For scientific applications, accounting,
  78. engineering and other demanding tasks, though, BCD may be just
  79. the thing you need.
  80.  
  81. The BCD math routines provided by PasWiz allow numbers of up to
  82. 255 digits long (the sign counts as a digit, but the decimal
  83. point doesn't). You may set the decimal point to any position
  84. you like, as long as there is at least one digit position to the
  85. left of the decimal.
  86.  
  87. Since Pascal doesn't support BCD numbers directly, we store the
  88. BCD numbers in strings. The results are not in text format and
  89. won't mean much if displayed. A conversion routine allows you to
  90. change a BCD number to a text string in any of a variety of
  91. formats.
  92.  
  93. Note that the BCD math handler doesn't yet track
  94. overflow/underflow error conditions. If you anticipate that this
  95. may be a problem, it would be a good idea to screen your input
  96. or to make the BCD range large enough to avoid these errors.
  97.  
  98. Let's start off by considering the BCD range. This is kept in
  99. two integer variables, LDigits and RDigits, which can be
  100. accessed by your program. These variables specify the maximum
  101. number of digits to the left and to the right of the decimal
  102. point. There must be at least one digit on the left, and the
  103. total number of digits must be less than 255. The BCD strings
  104. will have a length that's one larger than the total number of
  105. digits, to account for the sign of the number. The decimal point
  106. is implicit and doesn't take up any extra space.
  107.  
  108. It is assumed that you will only use one size of BCD number in
  109. your program-- there are no provisions for handling mixed-length
  110. BCD numbers. Of course, you could manage that yourself with a
  111. little extra work, if it seems like a useful capability. If you
  112. don't change LDigits or RDigits, the default size of the BCD
  113. numbers will be 32 (20 to the left, 11 to the right, 1 for the
  114. sign).
  115.  
  116.                            BCD Math                      page 4
  117.  
  118.                            Unit: BCD
  119.  
  120.  
  121.  
  122. Before doing any BCD calculations, you must have some BCD
  123. numbers! The BCDSet routine takes a number in text string form
  124. and converts it to BCD:
  125.  
  126. TextSt := '1234567890.50';
  127. Nr := BCDSet(TextSt);
  128.    { FUNCTION BCDSet (TextSt: String): String; }
  129.  
  130. If your numbers are stored as actual numbers, you can convert
  131. them to a text string with Pascal's Str procedure, then to BCD:
  132.  
  133. Str(Number, TextSt);
  134. Nr := BCDSet(TextSt);
  135.  
  136. BCD numbers can also be converted back to text strings, of
  137. course. You may specify how many digits to the right of the
  138. decimal to keep (the number will be truncated, not rounded). If
  139. the RightDigits value is positive, trailing zeros will be kept;
  140. if negative, trailing zeros will be removed. There are also
  141. various formatting options which may be used. Here's how it
  142. works:
  143.  
  144. FUNCTION BCDFormat (Nr: String; HowToFormat,
  145.                     RightDigits: Integer): String;
  146.  
  147. The HowToFormat value may be any combination of the following
  148. (just add the numbers of the desired formats together):
  149.  
  150.    0   plain number
  151.    1   use commas to separate thousands, etc
  152.    2   start number with a dollar sign
  153.    4   put the sign on the right instead of the left side
  154.    8   use plus sign instead of space if nr is not negative
  155.  
  156. The BCD math functions are pretty much self-explanatory, so I'll
  157. keep the descriptions brief. The single-parameter functions are
  158. listed on the next page.
  159.  
  160.                            BCD Math                      page 5
  161.  
  162.                            Unit: BCD
  163.  
  164.  
  165.  
  166. { absolute value }
  167. FUNCTION BCDAbs (Nr: String): String;
  168.  
  169. { cosine }
  170. FUNCTION BCDCos (Nr: String): String;
  171.  
  172. { cotangent }
  173. FUNCTION BCDCot (Nr: String): String;
  174.  
  175. { cosecant }
  176. FUNCTION BCDCsc (Nr: String): String;
  177.  
  178. { convert degrees to radians }
  179. FUNCTION BCDDeg2Rad (Nr: String): String;
  180.  
  181. { the constant "e" }
  182. FUNCTION BCDe: String;
  183.  
  184. { factorial }
  185. FUNCTION BCDFact (Nr: Integer): String;
  186.  
  187. { fractional part of number }
  188. FUNCTION BCDFrac (Nr: String): String;
  189.  
  190. { integer part of number }
  191. FUNCTION BCDInt (Nr: String): String;
  192.  
  193. { negation }
  194. FUNCTION BCDNeg (Nr: String): String;
  195.  
  196. { the constant "pi" }
  197. FUNCTION BCDpi: String;
  198.  
  199. { convert radians to degrees }
  200. FUNCTION BCDRad2Deg (Nr: String): String;
  201.  
  202. { secant }
  203. FUNCTION BCDSec (Nr: String): String;
  204.  
  205. { signum }
  206. FUNCTION BCDSgn (Nr: String): Integer;
  207.  
  208. { sine }
  209. FUNCTION BCDSin (Nr: String): String;
  210.  
  211. { square root }
  212. FUNCTION BCDSqrt (Nr: String): String;
  213.  
  214. { tangent }
  215. FUNCTION BCDTan (Nr: String): String;
  216.  
  217.                            BCD Math                      page 6
  218.  
  219.                            Unit: BCD
  220.  
  221.  
  222.  
  223. Notes on the single-parameter functions:
  224.  
  225.   The signum function returns an integer based on the sign of
  226.   the BCD number:
  227.  
  228.      -1   if the BCD number is negative
  229.       0   if the BCD number is zero
  230.       1   if the BCD number is positive
  231.  
  232.   BCDpi is accurate to the maximum level afforded by the BCD
  233.   functions. BCDe is accurate to as many as 115 decimal places.
  234.   The actual accuracy, of course, depends on the size of BCD
  235.   numbers you've chosen.
  236.  
  237.   The trigonometric functions (cos, sin, tan, sec, csc, cot)
  238.   expect angles in radians. BCDDeg2Rad and BCDRad2Deg will allow
  239.   you to convert back and forth between radians and degrees.
  240.  
  241.  
  242.  
  243. Here is a list of the two-parameter functions:
  244.  
  245.  
  246. { addition }
  247. FUNCTION BCDAdd (Nr1, Nr2: String): String;
  248.  
  249. { divide 1st by 2nd }
  250. FUNCTION BCDDiv (Nr1, Nr2: String): String;
  251.  
  252. { multiplication }
  253. FUNCTION BCDMul (Nr1, Nr2: String): String;
  254.  
  255. { subtract 2nd from 1st }
  256. FUNCTION BCDSub (Nr1, Nr2: String): String;
  257.  
  258. { raise to a power }
  259. FUNCTION BCDPower (Nr: String; Power: Integer): String;
  260.  
  261. { compare two numbers }
  262. FUNCTION BCDCompare (Nr1, Nr2: String): Integer;
  263.  
  264. The comparison function returns an integer which reflects how
  265. the two numbers compare to each other:
  266.  
  267.    -1   Nr1 < Nr2
  268.     0   Nr1 = Nr2
  269.     1   Nr1 > Nr2
  270.  
  271.                         Equipment Info                   page 7
  272.  
  273.                         Unit: Equipment
  274.  
  275.  
  276.  
  277. The equipment unit gives you information about the computing
  278. environment. This includes both installed software and hardware.
  279.  
  280. The first function allows you to determine if an "enhanced"
  281. keyboard (101-key) is installed. It may not be able to figure
  282. out what the keyboard is on some older not-quite-clone PCs, in
  283. which case it will take the safe way out and report that there
  284. is no enhanced keyboard. This function returns -1 if there is an
  285. enhanced keyboard present, 0 if not.
  286.  
  287. FUNCTION EnhKbd: Integer;
  288.  
  289. Want to know the type of processor (CPU) being used? Can do!
  290.  
  291. FUNCTION Processor: Integer;
  292.  
  293. The results will be reported as a number which can be decoded as
  294. follows:
  295.  
  296.    0    NEC V20
  297.    1    8088 or 8086
  298.    2    80186
  299.    3    80286
  300.    4    80386
  301.    5    80486
  302.  
  303. Maybe you'd like to check for a CD-ROM drive:
  304.  
  305. FUNCTION CDROM: Integer;
  306.  
  307. This tells you how many logical drives exist, if there is a
  308. CD-ROM available. If not, it will return 0. Note that the CD-ROM
  309. installation check conflicts with the GRAPHICS.COM installation
  310. check for DOS 4.0, due to some screw-up at IBM or Microsoft. I'm
  311. not yet sure whether DOS 5.0 is similarly afflicted.
  312.  
  313. The number of floppy drives installed is retrieved with this:
  314.  
  315. FUNCTION Floppies: Integer;
  316.  
  317. To get the number of serial (COM) ports and parallel (LPT)
  318. ports, use the following functions:
  319.  
  320. FUNCTION CommPorts: Integer;
  321.  
  322. FUNCTION PrtPorts: Integer;
  323.  
  324.                         Equipment Info                   page 8
  325.  
  326.                         Unit: Equipment
  327.  
  328.  
  329.  
  330. Now, there may be up to four floppy drives in a system; however,
  331. the AT CMOS data area only directly supports two. This makes it
  332. easy to find out what kind of drives the first two are, but not
  333. the second two, if any. Such is life.
  334.  
  335. PROCEDURE FloppyType (VAR Drive1, Drive2: Integer);
  336.  
  337. The results from FloppyType are returned as follows:
  338.  
  339.    0    no drive
  340.    1    5 1/4"    360K
  341.    2    5 1/4"    1.2M
  342.    3    3 1/2"    720K
  343.    4    3 1/2"    1.44M
  344.    5    3 1/2"    2.88M
  345.  
  346. Result codes of 6-7 are also available, but are not yet defined.
  347.  
  348. New memory types sure have burgeoned over the years... expanded,
  349. extended, and now XMS. There are routines to check all of these:
  350.  
  351. { amount of extended memory installed }
  352. FUNCTION AllExtMem: LongInt;
  353.  
  354. { BIOS extended memory available }
  355. FUNCTION GetExtM: LongInt
  356.  
  357. { amount of expanded memory  (a page is 16 Kbytes) }
  358. PROCEDURE GetEMSm (VAR TotalPages, FreePages: Integer);
  359.  
  360. { amount of XMS memory  (returned in kilobytes) }
  361. PROCEDURE GetXMSm (VAR LargestFreeBlock, TotalFree: LongInt);
  362.  
  363. When you're dealing with extended memory, whether it be
  364. BIOS-type or using the XMS standard, the results are returned in
  365. kilobytes. Multiply 'em by 1024 to convert to bytes. When you're
  366. dealing with expanded memory (EMS), the results are in pages of
  367. 16,384 bytes.
  368.  
  369.                         Equipment Info                   page 9
  370.  
  371.                         Unit: Equipment
  372.  
  373.  
  374.  
  375. A few more routines to get the versions of the EMS and XMS
  376. drivers, if any:
  377.  
  378. PROCEDURE GetEMSv (VAR MajorV, MinorV: Integer);
  379.  
  380. PROCEDURE GetXMSv (VAR MajorV, MinorV: Integer);
  381.  
  382. These return the major and minor version numbers as two separate
  383. integers. For example, EMS 4.0 would return major version 4,
  384. minor version 0.
  385.  
  386. It's nice to know a little about the operating environment. With
  387. the below routines, you can find out what the DOS version is;
  388. what version of 4DOS, if any, is in use; and whether Microsoft
  389. Windows is running.
  390.  
  391. PROCEDURE GetDOSv (VAR MajorV, MinorV: Integer);
  392.  
  393. PROCEDURE Get4DOSv (VAR MajorV, MinorV: Integer);
  394.  
  395. PROCEDURE WinCheck (VAR MajorV, MinorV: Integer);
  396.  
  397. These return results as major and minor version numbers, as
  398. discussed above. The Get4DOSv and WinCheck routines return
  399. zeroes if 4DOS and Windows, respectively, are not in use.
  400.  
  401. There are a couple of curious features of GetDOSv to keep in
  402. mind. If the version is 10 or higher, you're running under OS/2.
  403. DOS version 10 is actually OS/2 1.0, version 20 is OS/2 2.0, and
  404. so on. Secondly, if you're using DOS 5.0, the version reported
  405. may not be 5.0-- DOS 5.0 can be told to reply with a lower
  406. version number to allow badly written older software to run
  407. properly.
  408.  
  409. One final routine that should be of some value is the one that
  410. allows you to find out what kind of display is available. It
  411. tells you the specific adapter and whether the display is color
  412. or monochrome. There is one case in which it can be confused,
  413. however-- if the adapter is CGA, the display is assumed to be
  414. color, since there is no way for the computer to know any
  415. differently. So, although this routine provides a good idea of
  416. what is available, it would be a good idea to provide an option
  417. to tell the program that a monochrome display is attached.
  418. Microsoft normally uses "/B" for this purpose, so that might be
  419. a good standard to stick with.
  420.  
  421. PROCEDURE GetDisplay (VAR Adapter: Integer; VAR Mono: Boolean);
  422.  
  423. The adapter will be one of the following:
  424.  
  425.    1     MDA                  4     EGA
  426.    2     Hercules             5     MCGA
  427.    3     CGA                  6     VGA
  428.  
  429.                      Expression Evaluator               page 10
  430.  
  431.                          Unit: ExtMath
  432.  
  433.  
  434.  
  435. The expression evaluator solves numeric equations. It allows you
  436. to find the result of an expression contained in a string.
  437. Normal algebraic precedence is used, e.g. 4+3*5 evaluates to 19.
  438. The usual numeric operators (*, /, +, -, ^) are supported
  439. (multiply, divide, add, subtract, and raise to a power).
  440. Negation is also supported. Parentheses can be used for
  441. overriding the default order of operations.
  442.  
  443. You may use either double asterisk ("**") or caret ("^") symbols
  444. to indicate exponentiation.
  445.  
  446. The constant PI is recognized, as are the following functions:
  447.    ABS    absolute value        INT    integer
  448.    ACOS   inverse cosine        LOG    natural log
  449.    ASIN   inverse sine          SIN    sine
  450.    ATAN   inverse tangent       SQRT   square root
  451.    COS    cosine                TAN    tangent
  452.    FRAC   fraction
  453.  
  454. Trig functions expect angles in radians.
  455.  
  456. To evaluate an expression, you pass it to the evaluator as a
  457. string. You will get back either an error code or a real result.
  458. See the CALC.PAS program for a working example.
  459.  
  460. PROCEDURE Evaluate (Expression: String; VAR Result: Real;
  461.                     VAR ErrCode: Integer);
  462.  
  463. An expression evaluator adds convenience to any program that
  464. needs to accept numbers. Why make someone reach for a calculator
  465. when number crunching is what a computer does best?
  466.  
  467.                  Extensions to Pascal's Math            page 11
  468.  
  469.                         Unit: ExtMath
  470.  
  471.  
  472.  
  473. For the most part, the math routines in this library are
  474. designed to provide alternatives to the math routines that come
  475. with Pascal. Still, Pascal's own math support is quite adequate
  476. for many purposes, so there's no sense in ignoring it. Here are
  477. some functions which improve on Pascal's math.
  478.  
  479. { inverse cosine }
  480. FUNCTION ArcCos (Number: Real): Real;
  481.    { 1.0 >= Number >= -1.0 }
  482.  
  483. { inverse hyperbolic cosine }
  484. FUNCTION ArcCosH (Number: Real): Real;
  485.  
  486. { inverse cotangent }
  487. FUNCTION ArcCot (Number: Real): Real;
  488.  
  489. { inverse hyperbolic cotangent }
  490. FUNCTION ArcCotH (Number: Real): Real;
  491.  
  492. { inverse cosecant }
  493. FUNCTION ArcCsc (Number: Real): Real;
  494.  
  495. { inverse hyperbolic cosecant }
  496. FUNCTION ArcCscH (Number: Real): Real;
  497.  
  498. { inverse secant }
  499. FUNCTION ArcSec (Number: Real): Real;
  500.  
  501. { inverse hyperbolic secant }
  502. FUNCTION ArcSecH (Number: Real): Real;
  503.  
  504. { inverse sine }
  505. FUNCTION ArcSin (Number: Real): Real;
  506.    { 1.0 >= Number >= -1.0 }
  507.  
  508. { inverse hyperbolic sine }
  509. FUNCTION ArcSinH (Number: Real): Real;
  510.  
  511. { inverse hyperbolic tangent }
  512. FUNCTION ArcTanH (Number: Real): Real;
  513.  
  514. { ceiling: smallest integer >= specified number }
  515. FUNCTION Ceil (Number: Real): Real;
  516.  
  517. { hyperbolic cosine }
  518. FUNCTION CosH (Number: Real): Real;
  519.  
  520. { cotangent }
  521. FUNCTION Cot (Number: Real): Real;
  522.  
  523.                  Extensions to Pascal's Math            page 12
  524.  
  525.                         Unit: ExtMath
  526.  
  527.  
  528.  
  529. { cosecant }
  530. FUNCTION Csc (Number: Real): Real;
  531.  
  532. { convert degrees to radians }
  533. FUNCTION Deg2Rad (Number: Real): Real;
  534.  
  535. { the constant "e" }
  536. FUNCTION e: Real;
  537.  
  538. { error function }
  539. FUNCTION Erf (Number: Real): Real;
  540.  
  541. { factorial }
  542. FUNCTION Fact (Number: Integer): Real;
  543.  
  544. { floor: largest integer <= specified number }
  545. FUNCTION Floor (Number: Real): Real;
  546.  
  547. { log (base 10) }
  548. FUNCTION Log (Number: Real): Real;
  549.  
  550. { convert radians to degrees }
  551. FUNCTION Rad2Deg (Number: Real): Real;
  552.  
  553. { raise a number to a power }
  554. FUNCTION Raise (Number: Real; Power: Integer): Real;
  555.  
  556. { secant }
  557. FUNCTION Sec (Number: Real): Real;
  558.  
  559. { hyperbolic secant }
  560. FUNCTION SecH (Number: Real): Real;
  561.  
  562. { signum (integer) }
  563. FUNCTION SgnI (Number: Integer): Integer);
  564.  
  565. { signum (real) }
  566. FUNCTION SgnR (Number: Real): Integer);
  567.  
  568. { hyperbolic sine }
  569. FUNCTION SinH (Number: Real): Real;
  570.  
  571. { tangent }
  572. FUNCTION Tan (Number: Real): Real;
  573.  
  574. { hyperbolic tangent }
  575. FUNCTION TanH (Number: Real): Real;
  576.  
  577.                        Joystick Support                 page 13
  578.  
  579.                         Unit: Joystick
  580.  
  581.  
  582.  
  583. There's little enough to say about the joystick. A PC may have
  584. up to two of them. Normally, a joystick has two buttons, and
  585. returns a pair of coordinates which describe the position in
  586. which it is being held. The coordinates vary depending on the
  587. individual joystick, the computer involved, and other factors,
  588. so it is wise to provide a calibration routine to customize your
  589. program for the joystick(s) involved.
  590.  
  591. The FlightStick joystick has a dial for throttle control, which
  592. is available only in a one-joystick setup. The throttle value is
  593. returned as the Y coordinate of an imaginary second joystick.
  594.  
  595. Coordinates (X, Y), where X is the horizontal and Y the vertical
  596. coordinate, range from around 0 to around 150 on my FlightStick.
  597. Since these values may vary significantly, however, they are
  598. returned as words.
  599.  
  600. The state of the joystick buttons may be checked individually or
  601. all at once. If you need to know the state of multiple buttons,
  602. it is faster to do it all at once, but you may do it either way.
  603.  
  604. FUNCTION ButtonA1: Boolean;       { button 1 on 1st joystick }
  605. FUNCTION ButtonA2: Boolean;       { button 2 on 1st joystick }
  606. FUNCTION ButtonB1: Boolean;       { button 1 on 2nd joystick }
  607. FUNCTION ButtonB2: Boolean;       { button 2 on 2nd joystick }
  608.  
  609. PROCEDURE Buttons (VAR A1, A2, B1, B2: Boolean); { all buttons }
  610.  
  611. The joystick positions are handled internally by a rather
  612. unfortunate method involving a timer, due to the way IBM
  613. designed the joystick interface. This makes getting the position
  614. rather slow. To alleviate the problem, all positions are
  615. returned at once.
  616.  
  617. PROCEDURE Positions (VAR AX, AY, BX, BY: Word);
  618.  
  619. Joystick support is handled through a set of BIOS routines which
  620. were added to the PC around 1985. These routines are not present
  621. in some of the oldest PCs.
  622.  
  623.                        Keyboard Control                 page 14
  624.  
  625.                         Unit: Keyboard
  626.  
  627.  
  628.  
  629. The keyboard is not a particularly exciting or glamorous device.
  630. In fact, we tend to forget about it except when it gets in the
  631. way. Sometimes it's a hardware problem-- squishy or clacking
  632. keys, or perhaps a commonly-used key placed in an out-of-the-way
  633. location. Then again, sometimes it's the software that's the
  634. problem. There are many aspects of keyboard control, not all of
  635. which are necessarily related to input. This unit will let you
  636. handle the keyboard in ways you may not have realized were
  637. possible. Better yet, it can help make keyboard control easier
  638. than the users of your programs dreamed possible.
  639.  
  640. Let's start out with keyboard output. Yep, not input-- output.
  641. We can stuff up to 15 keys into the keyboard buffer. Why would
  642. we ever want to do this? Perhaps to allow your program to pop-up
  643. a TSR automatically, to start another program after your program
  644. ends, or for creating key macros. You can enter extended key
  645. codes (like function keys) by using CHR$(0) before the scan
  646. code.
  647.  
  648. PROCEDURE TypeIn (Keys: String);
  649.  
  650. The usual keyboard action is quite sluggish. We can make it a
  651. lot crisper by changing the key repeat rate and the delay before
  652. repeating. This will work on ATs, but not PC/XT systems.
  653.  
  654. PROCEDURE SpeedKey (RepDelay, RepRate: Integer);
  655.  
  656. The delay may be 0-3 (1 by default):
  657.  
  658.    0      250 milliseconds
  659.    1      500 milliseconds
  660.    2      750 milliseconds
  661.    3        1 second
  662.  
  663. The repeat rate may be 0-31 (11 by default). The larger the
  664. number, the slower the speed-- 0 is around 30 cps, and 31 is
  665. around 2 cps.
  666.  
  667. I generally prefer to have the keyboard cranked up to full
  668. speed, using RepDelay and RepRate both set to zero. This may be
  669. a bit too zippy for some people, and may cause keyboard buffer
  670. overflows with some games. Experiment with it to see what you
  671. like best.
  672.  
  673. Of course, there may be reasons to make keyboard repeat less
  674. sensitive instead! That might be a good idea in programs written
  675. for small children, for example. You can adjust the keyboard
  676. equally well in either direction.
  677.  
  678.                        Keyboard Control                 page 15
  679.  
  680.                         Unit: Keyboard
  681.  
  682.  
  683.  
  684. Pascal allows you to control one of the keys which can interrupt
  685. your program, namely the Break key. There's another dangerous
  686. key which PasWiz allows you to control-- the PrtSc (PrintScreen)
  687. key. PrtSc may not seem like a hazard at first glance, but if
  688. it's pressed by accident with no printer ready, or in a graphics
  689. mode which PrtSc doesn't understand how to print, the results
  690. can be pretty messy. So, we let you turn it off or on:
  691.  
  692. PROCEDURE SetPrtSc (PrtScON: Boolean);
  693.  
  694. Use FALSE to turn it off or TRUE to turn it back on. If you turn
  695. off PrtSc, you MUST remember to turn it back on again before
  696. your program ends! Otherwise, an interrupt vector will point
  697. into nowhere, causing probable chaos the next time PrtSc is
  698. pressed.
  699.  
  700. Regardless of whether you've turned the PrtSc key off, you can
  701. print the screen yourself just as if PrtSc had been pressed:
  702.  
  703. PROCEDURE PrintScreen;
  704.  
  705. Now here's a strange one for you. When IBM brought out the
  706. 101-key keyboard, called the "enhanced" keyboard, they did
  707. something bizarre to the BIOS. They still allowed old keyboard
  708. calls to work, but they filtered out the new key codes so no one
  709. would see them. This made sure that no one would be able to use
  710. the capabilities of the "enhanced" keyboard without rewriting
  711. their programs. So, the keyboard has been around for years, and
  712. there are still few programs that even notice when you press
  713. F11. Pascal does not support the enhanced keyboard at all.
  714. Fortunately, PasWiz -does-. You can find out if an enhanced
  715. keyboard is installed with the EnhKbd function, which is in the
  716. Equipment unit.
  717.  
  718. If there is an enhanced keyboard installed, you can activate it
  719. with this:
  720.  
  721. PROCEDURE SetEnhKbd (Enhanced: Boolean);
  722.  
  723. With enhanced keyboard support activated, all key requests that
  724. used the old services are translated to the new services. So,
  725. SetEnhKbd affects the ReadKey (in the CRT unit that comes with
  726. Pascal) and other Pascal functions as well as other PasWiz
  727. keyboard routines. Note that you MUST deactivate enhanced
  728. keyboard support before ending your program. Otherwise, an
  729. interrupt vector will point into nowhere, probably causing a
  730. crash on the next keypress!
  731.  
  732.                        Keyboard Control                 page 16
  733.  
  734.                         Unit: Keyboard
  735.  
  736.  
  737.  
  738. If you're about to request important input, you may not want to
  739. chance having it answered from results of the keyboard buffer--
  740. could be that the user meant those keys for another purpose. In
  741. that case, it's a good approach to clear out the keyboard buffer
  742. just before the input:
  743.  
  744. PROCEDURE ClearKbd;
  745.  
  746. No keyboard unit would be complete without a selection of
  747. routines to check the shift states and get or set the keyboard
  748. toggles. Let's start with the toggles, which are so called
  749. because they get toggled from one state to another:
  750.  
  751. FUNCTION CapsOn: Boolean;         { Caps Lock }
  752.  
  753. FUNCTION InsertOn: Boolean;       { Insert }
  754.  
  755. FUNCTION NumOn: Boolean;          { Num Lock }
  756.  
  757. FUNCTION ScrollOn: Boolean;       { Scroll Lock }
  758.  
  759. You can also turn the toggles off or on. It's courteous to
  760. restore the original toggle states once you end your program, so
  761. you might want to save the original values for that purpose.
  762. Then again, I guess that doesn't apply if your program is
  763. designed for the specific purpose of setting the toggles!
  764.  
  765. PROCEDURE SetCaps (CapsLock: Boolean);        { Caps Lock }
  766.  
  767. PROCEDURE SetInsert (InsertKey: Boolean);     { Insert }
  768.  
  769. PROCEDURE SetNum (NumLock: Boolean);          { Num Lock }
  770.  
  771. PROCEDURE SetScroll (ScrollLock: Boolean);    { Scroll Lock }
  772.  
  773. Does anyone actually use ScrollLock for anything?  Just
  774. curious...
  775.  
  776.                        Keyboard Control                 page 17
  777.  
  778.                         Unit: Keyboard
  779.  
  780.  
  781.  
  782. The shift keys are unique in many respects. They don't return
  783. codes that can be detected with ReadKey or stuffed into the
  784. keyboard buffer; several can be pressed at the same time; and
  785. they don't repeat. You can detect 'em with PasWiz, at any rate:
  786.  
  787. FUNCTION AltPress: Boolean;         { any ALT }
  788.  
  789. FUNCTION CtrlPress: Boolean;        { any CTRL }
  790.  
  791. FUNCTION ShiftPress: Boolean;       { any SHIFT }
  792.  
  793. FUNCTION LAltPress: Boolean;        { left ALT }
  794.  
  795. FUNCTION LCtrlPress: Boolean;       { left CTRL }
  796.  
  797. FUNCTION LShiftPress: Boolean;      { left SHIFT }
  798.  
  799. FUNCTION RAltPress: Boolean;        { right ALT }
  800.  
  801. FUNCTION RCtrlPress: Boolean;       { right CTRL }
  802.  
  803. FUNCTION RShiftPress: Boolean;      { right SHIFT }
  804.  
  805. NOTE that LAltPress, LCtrlPress, RAltPress, and RCtrlPress are
  806. ONLY available for enhanced keyboards. They will not return
  807. useful results on older keyboards.
  808.  
  809.                          String Stuff                   page 18
  810.  
  811.                          Unit: Strings
  812.  
  813.  
  814.  
  815. Strings have always been something of an afterthought in Pascal.
  816. This unit brings in the heavy artillery! The PasWiz string
  817. routines may be divided into the following categories:
  818. comparison, compression, encryption, extraction, searching, and
  819. miscellaneous (mostly alteration). Let's take up these
  820. categories one at a time.
  821.  
  822. The compression routines are designed to work with ordinary text
  823. strings. The strings may not contain IBM extended-ASCII codes
  824. (CHR($80)-CHR($FF)), as these are used in the compression.
  825. Compression works on spaces, which will give you an average of
  826. 15% compression on normal text. If you compress printable text
  827. (i.e., no control codes), you'll get printable text in return,
  828. which makes these routines handy for use with text files.
  829. Compression and decompression is done at an extreme rate of
  830. speed and will not affect the timing of your program in any
  831. noticeable fashion.
  832.  
  833. FUNCTION Bsq (St: String): String;     { compress a string }
  834.  
  835. FUNCTION BUsq (St: String): String;    { uncompress a string }
  836.  
  837. Comparing two strings is easy enough in Pascal, but not as
  838. flexible as might be desired for some applications. You can tell
  839. if two strings match exactly, but not if they're reasonably
  840. close matches. PasWiz has two fuzzy comparison routines which
  841. can help.
  842.  
  843. The Soundex routine uses a long-established algorithm to
  844. convert a word into a code which represents the sound of the
  845. word. It is fast and can work well under properly defined
  846. circumstances; for instance, it will tell you that "Smith"
  847. sounds just like "Smythe", but not like "Banks". Between the
  848. need for speed and the vagaries of the English language,
  849. however, you may find matches which don't work as well. Soundex
  850. is certain that "Knight" sounds just like "Smashed", for
  851. example. So, it may be perfect for something like a phone book,
  852. but not for a spelling checker!
  853.  
  854. FUNCTION Soundex (St: String): String;
  855.  
  856. The Bickel routine, on the other hand, tells you how closely two
  857. words match. This is a relative measure, not an absolute
  858. measure, so you'd probably want to search through an entire
  859. dictionary and just keep the words which matched best. The
  860. Bickel algorithm is slower than Soundex but is much more
  861. precise.
  862.  
  863. FUNCTION Bickel (St1, St2: String): Integer;
  864.  
  865.                          String Stuff                   page 19
  866.  
  867.                          Unit: Strings
  868.  
  869.  
  870.  
  871. There are many cases in which you might want to keep data
  872. private. The PasWiz encryption routines provide a simple and
  873. extremely fast method for password-protecting text. The
  874. encryption technique is trivial and will not withstand any
  875. concerted attack, but should suffice for casual use. It will
  876. help if you pick a longish password of unusual characters, for
  877. example '[^.mE@@&o}' (don't use this example itself, please)!
  878.  
  879. There are two encryption routines (which also work as decryption
  880. routines). The first is designed to produce printable, if
  881. bizarre-looking, results which are suited for use with text
  882. files. Text to be encrypted by this routine may not include IBM
  883. extended-ASCII characters (CHR($80) - CHR($FF)), since these are
  884. used to insure printable text.
  885.  
  886. FUNCTION CipherP (St, Passwd: String): String;
  887.  
  888. The other routine will work with any sort of text, but is not
  889. guaranteed to produce printable results. So, it's not suited for
  890. use with text files.
  891.  
  892. FUNCTION Cipher (St, Passwd: String): String;
  893.  
  894. Of the extraction routines, two are merely convenient
  895. rephrasings of the Copy function which allow you to grab a
  896. substring from the left or right side of a string:
  897.  
  898. FUNCTION Left (St: String; Len: Integer): String;
  899.  
  900. FUNCTION Right (St: String; Len: Integer): String;
  901.  
  902. Another extraction routine is more interesting. It allows you to
  903. extract a substring from a string which contains delimited
  904. information. For instance, consider the following name and
  905. address string. It has three fields, each separated by an
  906. asterisk. We can use Extract to grab any individual field:
  907.  
  908. St := 'Tom Hanlin*3544 E. Southern Ave. #104*Mesa, AZ 85204';
  909. FOR PrtAddress := 1 TO 3 DO BEGIN
  910.    AddressLine := Extract(St, '*', PrtAddress);
  911.    WriteLn(AddressLine);
  912. END;
  913.  
  914. The extract function is defined as follows:
  915.  
  916. FUNCTION Extract (St, Delimiter: String;
  917.                   Index: Integer): String;
  918.  
  919. If you try to extract a field which doesn't exist, a null string
  920. will be returned. Field delimiters may be anything at all, by
  921. the way-- one possible use for Extract might be to block-read a
  922. text file, splitting it apart in memory by using the carriage
  923. return and linefeed as a delimiter.
  924.  
  925.                        String Stuff                     page 20
  926.  
  927.                        Unit: Strings
  928.  
  929.  
  930.  
  931. PasWiz provides an assortment of string search routines. One is
  932. a simple modification of Pos which allows you to start the
  933. search at a given place in the string:
  934.  
  935. FUNCTION Instr (Start: Integer; SubSt, St: String): Integer;
  936.  
  937. Another works like Pos, but returns the last match rather than
  938. the first match:
  939.  
  940. FUNCTION RPos (SubSt, St: String): Integer;
  941.  
  942. Of course, you don't always want to search for something in
  943. specific. You might be more interested in finding the first
  944. character that fits into a given category or categories, like
  945. perhaps numbers or letters. No problem:
  946.  
  947. FUNCTION TypePos (ChType: Integer; St: String): Integer;
  948.  
  949. The ChType value is formed by adding the numbers which represent
  950. the desired categories. This can also be used to search for the
  951. first character which is not of a given type, since the
  952. categories are exclusive:
  953.  
  954.     1    alphabetic
  955.     2    numeric
  956.     4    symbols
  957.     8    control codes (ASCII 0-31, 127)
  958.    16    graphics codes (ASCII 128-255)
  959.    32    space (ASCII 32)
  960.  
  961. That covers the string routines which can be readily
  962. categorized. Most of the remaining routines are designed to
  963. alter a string in one way or another. This includes being able
  964. to remove selected characters, substrings, types of characters,
  965. or repeated characters from a string; trimming the left or right
  966. side of a string of blanks; converting to uppercase, lowercase,
  967. or using the correct capitalization for a proper name; replacing
  968. one substring with another; reversing a string; and forming a
  969. new string by repeating a given substring.
  970.  
  971. The "case", "trim", and "reverse" functions are pretty much
  972. self-explanatory:
  973.  
  974. FUNCTION LowerCase (St: String): String;    { lowercase }
  975.  
  976. FUNCTION NameCase (St: String): String;     { name case }
  977.  
  978. FUNCTION UpperCase (St: String): String;    { upper case }
  979.  
  980. FUNCTION LTrim (St: String): String;        { left trim }
  981.  
  982. FUNCTION RTrim (St: String): String;        { right trim }
  983.  
  984. FUNCTION Reverse (St: String): String;      { reverse }
  985.  
  986.                        String Stuff                     page 21
  987.  
  988.                        Unit: Strings
  989.  
  990.  
  991.  
  992. The Crunch function removes adjacent repetitions of a substring.
  993. This is particularly handy for parsing user input, for example--
  994. you can use it to remove repeated spaces between options, etc.
  995.  
  996. FUNCTION Crunch (SubSt, St: String): String;
  997.  
  998. The Dupe function forms a string by repeating a substring. It's
  999. handy when you need a string of a given number of spaces,
  1000. zeroes, or nulls. It can also be used for drawing horizontal
  1001. lines and other applications.
  1002.  
  1003. FUNCTION Dupe (Count: Integer; SubSt: String): String;
  1004.  
  1005. There are many times when it's nice to be able to replace all
  1006. occurrences of one substring with another. PasWiz can do that,
  1007. no problem. You don't have to worry about recursion, either--
  1008. each occurrence is replaced only once, even if the replacement
  1009. substring contains the target substring.
  1010.  
  1011. FUNCTION Replace (OldSubSt, NewSubSt, St: String): String;
  1012.  
  1013. Of course, you can delete a substring by replacing it with a
  1014. null string. It's faster to use the routine designed for that
  1015. purpose, though:
  1016.  
  1017. FUNCTION StripSt (SubSt, St: String): String;
  1018.  
  1019. You may also delete specified characters from a string:
  1020.  
  1021. FUNCTION StripCh (ChList, St: String): String;
  1022.  
  1023. Next, a routine which deletes specified types of characters from
  1024. a string. This can be very good for screening user input.
  1025.  
  1026. FUNCTION StripType (ChType: Integer; St: String): String;
  1027.  
  1028. The ChType value is formed by adding the numbers which represent
  1029. the desired categories:
  1030.  
  1031.     1    alphabetic
  1032.     2    numeric
  1033.     4    symbols
  1034.     8    control codes (ASCII 0-31, 127)
  1035.    16    graphics codes (ASCII 128-255)
  1036.    32    space (ASCII 32)
  1037.  
  1038. PasWiz also has a specialized variant on the Val function which
  1039. converts a number from a string to a WORD (or INTEGER) value. No
  1040. error checking is provided. This is very small and fast:
  1041.  
  1042.    FUNCTION WVal (St: STRING): WORD;
  1043.  
  1044.                             Music                       page 22
  1045.  
  1046.                          Unit: Music
  1047.  
  1048.  
  1049.  
  1050. Granted, the PC has never been known for its wonderful sound
  1051. capabilities. Still, it has more potential than you might guess,
  1052. especially given the utterly minimal Sound/Delay/NoSound
  1053. routines that are provided with Pascal. The Music unit makes it
  1054. much easier to use sounds by providing an actual music language.
  1055. The BACHINV and ENTERTNR demo programs demonstrate some of the
  1056. possibilities.
  1057.  
  1058. The PasWiz music language is nearly identical to that offered by
  1059. the BASIC PLAY statement. The major difference is that the "MB"
  1060. command (play the music as a background task) is not supported.
  1061. I'll add that later, if I get enough requests.
  1062.  
  1063. There are only two music procedures:
  1064.  
  1065. PROCEDURE ResetMF;
  1066.  
  1067. PROCEDURE PlayMF(Sounds: String);
  1068.  
  1069. The ResetMF procedure is used to reset all music parameters to
  1070. the default values. It would typically be used after finishing a
  1071. song to restore the music handler for the next song.
  1072.  
  1073. The PlayMF procedure is the one that does the real work. Here's
  1074. a list of the music commands supported:
  1075.  
  1076.    MB  play music as a background task (ignored)
  1077.    MF  play music as a foreground task (ignored)
  1078.    ML  legato (8/8 note length)
  1079.    MN  normal music (7/8 note length)
  1080.    MN  staccato (6/8 note length)
  1081.    Ln  Length of notes (n = 1-64; note length = 1/n)
  1082.    Nn  Note number (n = 0-84; 0 is a rest)
  1083.    On  Octave (n = 0-6, default 4)
  1084.    Pn  Pause (n = 1-64; pause length = 1/n)
  1085.    Tn  Tempo (n = 32-255, default 120; quarter notes/minute)
  1086.    <   move up an octave (max 6)
  1087.    >   move down an octave (min 0)
  1088.  
  1089. You can also use the actual letters of the notes (C, D, E, F, G,
  1090. A, and B). If you're not particularly musical, these correspond
  1091. to "do, re, mi, fa, so, la, ti" (with the final "do" being C
  1092. again, but an octave higher). To play a scale, you'd use
  1093. 'CDEFGAB>C'. The notes may be followed by dots, by note lengths,
  1094. and by sharp or flat symbols (a '+' or '#' for a sharp, a '-'
  1095. for a flat). For example, 'D-.' is a dotted D flat. The dot
  1096. means that the note will play for half again its usual length.
  1097. Dots can be repeated.
  1098.  
  1099. I might note (ahem) that the so-called "ANSI" music offered by
  1100. some BBSes and comm programs is based on this same music
  1101. language. If you're writing telecomm software, this unit makes
  1102. it trivial to add sound.
  1103.  
  1104.                             Mouse                       page 23
  1105.  
  1106.                          Unit: Mouse
  1107.  
  1108.  
  1109.  
  1110. Considering the ubiquity of the mouse these days, it's a marvel
  1111. to me that none of the popular programming languages provides
  1112. any support for it. Well, BASIC supports it via light pen
  1113. emulation, but that scarcely counts. Anyway, this is a simple
  1114. little unit which provides you direct access to the mouse
  1115. driver. It will work with any Microsoft-compatible mouse driver.
  1116.  
  1117. A few words are necessary on mouse handling. To begin with, the
  1118. best time to check for a mouse is immediately after you've
  1119. established the desired video mode. The mouse driver initializes
  1120. certain information when you check for it, so it's a good idea
  1121. to check for it only once, at the appropriate time.
  1122.  
  1123. The mouse cursor was implemented in a rather bizarre manner. If
  1124. you call ShowCursor, you're guaranteed that the mouse cursor
  1125. will be visible; however, this also increments an internal
  1126. visibility flag. If you call ShowCursor multiple times, you will
  1127. also have to call HideCursor multiple times before the dang
  1128. cursor actually disappears.
  1129.  
  1130. The mouse driver was apparently implemented without any thought
  1131. for the future. In text mode, it returns coordinates based on
  1132. CGA hi-res graphics mode-- 640x200 instead of the expected
  1133. 80x25. If you use the mouse driver in text mode, you'll have to
  1134. compensate for this (divide coordinates by 8 to convert to text
  1135. mode, or multiply by 8 to convert to the mouse virtual mode).
  1136. The CGA low-res 320x200 graphics mode is implemented likewise.
  1137. It seems Microsoft thought that 640x200 would be the ultimate
  1138. resolution, so they translated everything to a 640x200 virtual
  1139. mode. Arrgh. Fortunately, this does not apply to video modes
  1140. other than text and CGA graphics.
  1141.  
  1142. I understand that it's possible to get the mouse working in
  1143. Hercules graphics mode, but I'm not sure what the details are.
  1144. If anyone out there knows, please let me know, and I'll pass it
  1145. along.
  1146.  
  1147. Since Microsoft was initially very tight-lipped about the mouse
  1148. functions, older mouse drivers for Microsoft-compatible rodents
  1149. don't necessarily have all the functions available (this
  1150. includes Logitech, amazingly enough). The Microsoft mouse driver
  1151. continues to be updated in a rapid and haphazard manner, so
  1152. keeping up-to-date is no guarantee. However, if you have any
  1153. problems with these routines, you can almost certainly clear
  1154. them up by getting a newer mouse driver. The routines in this
  1155. unit are almost all old, well-established functions. "Iffy" ones
  1156. are marked for your convenience.
  1157.  
  1158.                             Mouse                       page 24
  1159.  
  1160.                          Unit: Mouse
  1161.  
  1162.  
  1163.  
  1164. The first function to consider simply tells you whether a mouse
  1165. is available, and if so, how many buttons it has. It also resets
  1166. the mouse driver, so it should be used only at the beginning of
  1167. your program (or after changing the video mode).
  1168.  
  1169. FUNCTION Init: Integer;
  1170.    { returns 0 if no mouse, else # of buttons }
  1171.  
  1172. Most often, you'll want to know which mouse button(s) are
  1173. pressed and where the mouse cursor is:
  1174.  
  1175. FUNCTION LeftButton: Boolean;
  1176.    { TRUE if pressed }
  1177.  
  1178. FUNCTION MidButton: Boolean;
  1179.    { always FALSE on 2-button rodents }
  1180.  
  1181. FUNCTION RightButton: Boolean;
  1182.    { TRUE if pressed }
  1183.  
  1184. FUNCTION WhereX: Integer;
  1185.    { X-coord (see notes on previous page) }
  1186.  
  1187. FUNCTION WhereY: Integer;
  1188.    { Y-coord (see notes on previous page) }
  1189.  
  1190. As well as finding the current mouse information, it's possible
  1191. to find out what the mouse has been doing since you last
  1192. checked. Two sets of routines exist: one to find out how many
  1193. times a button was pressed and where it was at the last press,
  1194. and one to find out how many times a button was released and
  1195. where it was at the last release.
  1196.  
  1197. PROCEDURE LeftClick(VAR Count, X, Y: Integer);
  1198.  
  1199. PROCEDURE MidClick(VAR Count, X, Y: Integer);
  1200.  
  1201. PROCEDURE RightClick(VAR Count, X, Y: Integer);
  1202.  
  1203. PROCEDURE LeftRelease(VAR Count, X, Y: Integer);
  1204.  
  1205. PROCEDURE MidRelease(VAR Count, X, Y: Integer);
  1206.  
  1207. PROCEDURE RightRelease(VAR Count, X, Y: Integer);
  1208.  
  1209.                             Mouse                       page 25
  1210.  
  1211.                          Unit: Mouse
  1212.  
  1213.  
  1214.  
  1215. There's one more informational routine. It tells you the basic
  1216. mouse software and hardware stats: driver version, connector
  1217. type (serial, bus, etc), and IRQ used. This routine is slightly
  1218. hazardous in that, although Microsoft claims it has existed from
  1219. the first, other manufacturers (including Logitech) have taken
  1220. some time to implement it. In other words, it may not return
  1221. useful information. The routine conducts a self-check and will
  1222. return all zeroes if it suspects the information is not good,
  1223. but even so... proceed with care.
  1224.  
  1225. PROCEDURE Info(VAR Version: Real; VAR Connector, IRQ: Byte);
  1226.  
  1227. Connector info: 1=bus, 2=serial, 3=InPort, 4=PS/2,
  1228. 5=Hewlett-Packard IRQs: 0=PS/2; 2-5, 7 are actual IRQ numbers.
  1229. It is conceivable that higher IRQ numbers may be supported on
  1230. AT-type machines, though not by Microsoft.
  1231.  
  1232. Of course, you can set mouse info as well as retrieving it. The
  1233. following routines are pretty well self-explanatory (don't
  1234. forget the notes about the strange text-mode and CGA coordinate
  1235. handling, and cursor handling):
  1236.  
  1237. { hide the mouse cursor }
  1238. PROCEDURE HideCursor;
  1239.  
  1240. { (maybe) make the cursor visible }
  1241. PROCEDURE ShowCursor;
  1242.  
  1243. { set the cursor position }
  1244. PROCEDURE GotoXY(X, Y: Integer);
  1245.  
  1246. { set the cursor range }
  1247. PROCEDURE Window(X1, Y1, X2, Y2: Integer);
  1248.  
  1249. There are other possibilities supported by the mouse driver that
  1250. I have not implemented here. They're mostly on the rather
  1251. esoteric side and are not supported by anything except recent
  1252. Microsoft mouse drivers and perhaps some close compatibles, such
  1253. as Logitech.
  1254.  
  1255. Among the mouse capabilities I haven't implemented are finding
  1256. out how fast and in what direction the mouse is moving, the
  1257. coordinate size of the screen as far as the mouse is concerned,
  1258. finding out the video modes that the mouse driver understands,
  1259. setting mouse speed and sensitivity parameters, setting up an
  1260. interrupt-driven system for handling mouse events, and a few
  1261. others.
  1262.  
  1263.                             Mouse                       page 26
  1264.  
  1265.                          Unit: Mouse
  1266.  
  1267.  
  1268.  
  1269. None of these missing capabilities is particularly vital (or
  1270. even useful) for the average mouse application. However, if
  1271. you're interested in any of these capabilities, let me know
  1272. which ones, and I'll be glad to add them to PasWiz.
  1273.  
  1274. Note: if you're confused at how I can get away with duplicating
  1275. the names of existing procedures... well, it's easy enough.
  1276. Let's consider WhereX. It means one thing to Pascal's Crt unit
  1277. and another to the PasWiz Mouse unit. Since the Mouse unit
  1278. doesn't use the Crt unit, it has no problem with any ambiguity.
  1279. Existing programs that don't use the Mouse unit will likewise
  1280. have no problems, since they don't know about the new routine.
  1281. Suppose you want to use both the Crt and Mouse units together,
  1282. however? There's the rub!
  1283.  
  1284. You can specify a routine from a given unit by including the
  1285. unit name when you use the routine. For instance:
  1286.  
  1287. X := Mouse.WhereX;      { get the mouse cursor position }
  1288.  
  1289. X := Crt.WhereX;        { get the normal cursor position }
  1290.  
  1291. This allows multiple units to use the same names for things.
  1292. While this may seem like a bit of a pain, since you have to
  1293. specify which you want, it has a major built-in advantage if
  1294. used properly. What's properly? When a routine in one unit works
  1295. just like a routine by the same name in another unit. When I
  1296. call the mouse routine "WhereX", for instance, I've also told
  1297. you what it is for and how to use it. So, the name itself
  1298. contains a lot of useful information on how to use the routine!
  1299. That's what I call a major advantage.
  1300.  
  1301.